import util from '../base/util'

class texter{
  constructor(x, y, w, h, icon){
    this.x = x
    this.y = y
    this.w = w
    this.h = h
    this.txt_cvs = wx.createCanvas()
    this.txt_ctx = this.txt_cvs.getContext('2d')
    this.txt_cvs.height = 24
    this.txt_cvs.width = 84
    //this.txt_ctx.font = "9px Arial"
    if (icon){
      this.icon = wx.createImage()
      this.icon.src = icon
    }
    //console.log(this.txt_ctx.font + ";" + this.txt_cvs.width + ";" + this.txt_cvs.height)
  }
  draw(text, color = 'white'){
    this.txt_ctx.clearRect(0, 0, this.txt_cvs.width, this.txt_cvs.height)
    //this.txt_ctx.fillStyle = 'red'
    //this.txt_ctx.fillRect(0, 0, this.txt_cvs.width, this.txt_cvs.height)
    let ofst = 0
    if (this.icon){
      this.txt_ctx.drawImage(this.icon, 0, 0, this.icon.width, this.icon.height, 20, 4, 10 * this.w / this.h, 10)
      ofst = 20
    }

    this.txt_ctx.fillStyle = color
    this.txt_ctx.fillText(text, (this.txt_cvs.width - ofst - this.txt_ctx.measureText(text).width) * 0.5 + ofst, this.txt_cvs.height * 0.65)
  }
  pointIsIn(x, y){
    return x > this.x - 0.1 && x < this.x + 0.1 && y > this.y - 0.1 && y < this.y + 0.1
  }
}

class item {
  constructor(parent, name, x, y, w, h){
    this.parent = parent
    this.name = name
    this.txt = new texter(x, y, w, h, 'images/astray/' + this.name + '2.png')
    this.count = 3
  }
  updateCount(count = - 1){
    let ret = this.count + count
    if (ret >= 0){
      this.count  = ret
      this.parent.__drawText(this.txt, this.count.toString())
      let t = new this.parent.THREE.CanvasTexture(this.txt.txt_cvs)
      t.minFilter = this.parent.THREE.LinearFilter
      this.obj.material.map = t
      this.obj.material.needsUpdate = true
      return true
    }else
      return false
  }
  async initRemoteCount(openid){
    let inf = (await util.request({
      api: "astray/playerInfo",
      data: {openid: openid,
             type: this.name}})).data
    this.count = inf.count || 0
    this.updateCount(0)
  }
}

class bombItem extends item {
  constructor(parent){ 
    super(parent, 'bomb', 1.8, 1.8, 0.6, 0.3)
  }
}

class shieldItem extends item {
  constructor(parent){
    super(parent, 'shield', 1.8, 1.4, 0.6, 0.3)
  }
}

class smallItem extends item{
  constructor(parent){
    super(parent, 'small', 1.8, 1.0, 0.6, 0.3)
  }
}

export default class astrayInfo {
  constructor(){
    this.level_txt = new texter(0.3, 2.7, 0.6, 0.3)
    this.time_txt = new texter(1.8, 2.7, 0.6, 0.3)
    this.coin_txt = new texter(1.1, 2.7, 0.6, 0.3, 'images/astray/coin.png')
    this.items = [new bombItem(this), new shieldItem(this), new smallItem(this)]
    this.delay_txt = new texter(1.8, 0, 0.6, 0.3)
    this.exit_txt = new texter(0.3, 0, 0.6, 0.3)
    this.aspect = canvas.width / canvas.height
  }

  __drawText(texter, text, isfirst, color = 'white'){
    texter.draw(text, color)
    if (isfirst){
      let t = new this.THREE.CanvasTexture(texter.txt_cvs)
      t.minFilter = this.THREE.LinearFilter
      let mtl = new this.THREE.SpriteMaterial({map: t})
      let obj = new this.THREE.Sprite(mtl)
      //obj.scale.set(dw / canvas.width, dh / canvas.width)
      obj.position.set(texter.x, texter.y, 1)
      obj.scale.set(texter.w, texter.h)
      this.scene.add(obj)
      return obj
    }else
      return null
  }

  initialize(scene, THREE, level, openid, loader, camera){
    this.scene = scene
    this.THREE = THREE
    this.loader = loader
    this.camera = camera
    this.lv = level
    this.openid = openid
    this.coins = 0
    this.objs = {}
    this.objs.level = this.__drawText(this.level_txt, 'Level ' + this.lv, true)
    this.objs.time = this.__drawText(this.time_txt, '0', true)
    this.objs.coins = this.__drawText(this.coin_txt, "0", true)
    for (let i in this.items){
      this.items[i].obj = this.__drawText(this.items[i].txt, this.items[i].count.toString(), true)
      this.objs[this.items[i].name] = this.items[i].obj
    }
    this.objs.delay = this.__drawText(this.delay_txt, '0', true)
    this.objs.exit = this.__drawText(this.exit_txt, '退出', true, 'orange')
    this.start_time = new Date().getTime()

    /*var t = Math.tan(this.THREE.Math.degToRad( this.camera.fov ) / 2 )
    var h = t * 2 * 4;
    console.log(h + ";" + h * this.camera.aspect)*/
    /*let g = new this.THREE.PlaneGeometry(0.3, 0.15)
    this.loader.load('images/astray/escape.png', t => {
      let m = new this.THREE.MeshPhongMaterial({map: t})
      let ret = new this.THREE.Mesh(g, m)
      ret.position.set(0.3, 0.3, 1)
      this.scene.add(ret)
    })*/
  }
  updateScene(dx, dy){
    for (let i in this.objs){
      this.objs[i].position.x += dx
      this.objs[i].position.y += dy
    }
  }

  control(x, y){

    //https://stackoverflow.com/questions/13055214/mouse-canvas-x-y-to-three-js-world-x-y-z
    let vec = new this.THREE.Vector3(( x / window.innerWidth ) * 2 - 1, - ( y / window.innerHeight ) * 2 + 1, 0.5)
    let pos = new this.THREE.Vector3()
    vec.unproject( this.camera )
    vec.sub(this.camera.position ).normalize()
    let dis = (1 - this.camera.position.z) / vec.z
    pos.copy(this.camera.position).add(vec.multiplyScalar(dis))
    let dx = pos.x - this.camera.position.x + 1
    let dy = pos.y - this.camera.position.y + 1

    for (let i in this.items)
      if (this.items[i].txt.pointIsIn(dx, dy) && this.items[i].updateCount())
        return this.items[i].name

    if (this.exit_txt.pointIsIn(dx, dy))
      return "exit"
    else
      return ""
    //let dx = (0.3 + 0.6 / 2 - canvas.width * 0.5) / canvas.width, dy = - (0.3 + 0.3 / 2 - canvas.height * 0.5) / canvas.height / this.aspect
    //console.log(dx + ";" + dy)
  }

  updateTime(){
    this.current_time = new Date().getTime() - this.start_time
    this.cost_time = (this.current_time / 1000).toFixed(2)
    this.__drawText(this.time_txt, this.cost_time.toString())
    let t = new this.THREE.CanvasTexture(this.time_txt.txt_cvs)
    t.minFilter = this.THREE.LinearFilter
    this.objs.time.material.map = t
    this.objs.time.material.needsUpdate = true
  }
  updateDelay(delay, color = 'white'){
    this.__drawText(this.delay_txt, delay.toString(), false, color)
    let t = new this.THREE.CanvasTexture(this.delay_txt.txt_cvs)
    t.minFilter = this.THREE.LinearFilter
    this.objs.delay.material.map = t
    this.objs.delay.material.needsUpdate = true
  }
  updateCoins(){
    this.coins++
    this.__drawText(this.coin_txt, this.coins.toString())
    let t = new this.THREE.CanvasTexture(this.coin_txt.txt_cvs)
    t.minFilter = this.THREE.LinearFilter
    this.objs.coins.material.map = t
    this.objs.coins.material.needsUpdate = true
  }

  finish(mode){
    //if (mode == "single")
      util.request({
        api: "astray/recordstage",
        data: {openid: this.openid, 
              stage: this.lv,
              coin: this.coins, 
              type: mode,
              cost: this.cost_time}})
      .then(res => {
          //console.log(res)
      })
  }
}
